package com.xinqi.common.third.word;

import com.xinqi.common.third.word.utils.ParticipleUtils;
import lombok.Data;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 余弦相似度分析
 *
 * @author linkai
 * @date 2023/2/22
 */
public final class ShortTextAnalyse {

    /**
     * 使用余弦相似度分析2则短文相识度
     *
     * @param text1 短文1
     * @param text2 短文2
     * @return 相似度
     */
    public static double analyse(String text1, String text2) {
        Map<String, int[]> resultMap = new HashMap<>();
        //统计
        statistics(resultMap, ParticipleUtils.participle(text1), 1);
        statistics(resultMap, ParticipleUtils.participle(text2), 0);
        //计算类
        CalculationData calculation = new CalculationData();
        resultMap.forEach((k, arr) -> {
            calculation.setNumerator(calculation.getNumerator() + arr[0] * arr[1]);
            calculation.setElementA(calculation.getElementA() + arr[0] * arr[0]);
            calculation.setElementB(calculation.getElementB() + arr[1] * arr[1]);
        });
        return calculation.result();
    }

    /**
     * 组合词频向量
     *
     * @param words     词列表
     * @param direction 方向
     */
    private static void statistics(Map<String, int[]> map, List<String> words, int direction) {
        if (null == words || words.size() == 0) {
            return;
        }
        int[] in;
        boolean flag = direction == 1;
        for (String word : words) {
            int[] wordD = map.get(word);
            if (null == wordD) {
                if (flag) {
                    in = new int[]{1, 0};
                } else {
                    in = new int[]{0, 1};
                }
                map.put(word, in);
            } else {
                if (flag) {
                    wordD[0]++;
                } else {
                    wordD[1]++;
                }
            }
        }
    }

    /**
     * 计算数据
     **/
    @Data
    public static class CalculationData {
        private double elementA;
        private double elementB;
        private double numerator;

        public double result() {
            return numerator / Math.sqrt(elementA * elementB);
        }
    }

}
